<?php
/*

This script is copyright © 2009 Chicago IT Systems S.L. and licensed under the GNU General Public
License v3
http://www.gnu.org/licenses/gpl.html

Author: Gustave (Ted) Stresen-Reuter
Home page: http://tedmasterweb.com

INTRO

This script presents a long, scrolling list of case activity. The presentation is similar to the 
"case" view in FogBugz, but rather than showing just one case, it shows all the cases for a given
filter. I find this particularly useful for sharing my task list with my clients as it allows them
to see exactly what is going on and reply to a specific case via email if there is something they
need to communicate.

SYSTEM REQUIREMENTS
PHP 5
PEAR with the HTTP_Request package (HTTP_Request2 will probably work as well)
http://pear.php.net/package/HTTP_Request/
PHP XSL Extension (included in PHP 5, but needs to be compiled in via --with-xsl[=DIR])
http://es.php.net/manual/en/book.xsl.php

TO USE THIS SCRIPT

1.  In FogBugz, create filters for each case list you want to make available. For example, if I want
    all open cases for a given client, I can do a search on the client's name indicating the results
    should only show open cases. I can then save that search as a filter.

2.  A few lines down, configure some method for determining which filter to show. The method shown 
    intends to make guessing difficult and thus keep uninvited eyes out without requiring any
    authentication. YMMV

3.  Configure the variables shown below.

RECOMMENDATION

Enable zlib.output_compression in your php.ini file. Since there is a lot of HTML being output by
this script, enabling compression will speed it up A LOT.

*/

/* set this to the URL for your FogBugz installation, On Demand users can use their normal URL */
$url = '';


/* set this to the username for your FogBugz installation */
$email = '';


/* 
Set this to the password for your FogBugz installation.
The only alternative to storing your password in this file is to manually obtain the token and set
the $token variable below to that string. Note then that this script can only be used from the 
computer you logged on from. In other words, the script loses its portability. Instructions for 
manually logging on and obtaining a token can be found here:
http://www.fogcreek.com/FogBugz/docs/60/topics/advanced/API.html?isl=105573
*/
$password = '';


/* set this to a location writable by the web server, since PHP lacks an Application scope */
$path2fogbugztoken = '/tmp/fogbugztoken';


/* Use some method to determine which filter to use */
@include_once('config.php');


/* DO NOT CHANGE ANYTHING BELOW THIS LINE, unless you are setting the token manually */



$path2fogbugz2html = dirname('.').'/FobBugz2HTML.xsl';
$token = @file_get_contents( $path2fogbugztoken );



/*
We require the PEAR HTTP_Request package.
This can usually be installed on *nix with `pear install HTTP_Request`
*/
require_once('HTTP/Request.php');

if ( $token == false )
{
    $cmd = "$url?cmd=logon&email=$email&password=$password";
    $req =& new HTTP_Request( $cmd );
    if (!PEAR::isError($req->sendRequest())){
        $token_xml = $req->getResponseBody();
    }
    
    $pattern = '/CDATA\[(.+?)\]/';
    $total_matches = preg_match ( $pattern, $token_xml, $matches );
    
    if ( $matches[1] != '' )
    {
        $token = $matches[1];
        $fp = fopen ( $path2fogbugztoken, 'w' );
        fwrite ( $fp, $token );
        fclose ( $fp );
    }
    else
    {
        echo "<pre>\n$token_xml";
        print_r ( $matches );
        echo "</pre>";
        die('Failed to find a token');
    }
}
else
{
    $req =& new HTTP_Request( '' );
}

/* Update only if the request does not meet the session */
if ( $_SESSION['filter'] != $ixFilter )
{
    $cmd = "$url?cmd=saveFilter&sFilter=$ixFilter&token=$token";
    $req->setURL($cmd);
    $req->sendRequest();
    $_SESSION['filter'] = $ixFilter;
}

$cmd = "$url?cmd=search&cols=sTitle,sLatestTextSummary,ixBugEventLatestText,sArea,ixCategory,sCategory,ixStatus,sStatus,ixPriority,sPriority,ixFixFor,sFixFor,hrsOrigEst,hrsCurrEst,hrsElapsed,dtOpened,dtResolved,dtClosed,sTicket,dtDue,ixRelatedBugs,events&token=$token";
$req->setURL($cmd);
$req->sendRequest();
if($req->getResponseBody() !== FALSE) {
	// convert URLs in the body to A elements (links)
	$p = '/http(s?):\/\/[a-z0-9\-\.]+\.[a-z]{2,4}(:[0-9]{,5})?\/?[a-z0-9\!\?\+\%\.\,\-_\&\=\/]*/i';
	$output = preg_replace($p, '<a href="$0">$0</a>', $req->getResponseBody());
	$xml = DOMDocument::loadXML($output);
	$xsl = DOMDocument::load($path2fogbugz2html);
	
	$proc = new XSLTProcessor();
	$proc->importStylesheet ( $xsl );
	$proc->setParameter ( '', Array('project_title'=>$project_title) );
	
	// convert URLs to links
	$output = $proc->transformToXML ( $xml );
	echo $output;
} else {
    echo "There was a problem fetching the data from fogbugz.";
}
